package com.yfp.org.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.util.StrUtil;
import com.yfp.org.domain.TCounty;
import com.yfp.org.domain.dto.*;
import com.yfp.org.domain.entity.Area;
import com.yfp.org.domain.vo.*;
import com.yfp.org.mapper.MachineMapper;
import com.yfp.org.service.*;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class DashboardServiceImpl implements DashboardService {

    @Resource
    private OrderListService orderListService;
    @Resource
    private OrderComboService orderComboService;
    @Resource
    private PositionService positionService;
    @Resource
    private MachineMapper machineMapper;
    @Resource
    private AreaService areaService;
    @Resource
    private TCountyService tCountyService;

    @Override
    public ProfileBasicInfoVO profileBasicInfo() {
        // 获取小程序/设备订单数量
        OrderTypeDTO orderTypeCount = orderListService.getOrderTypeCount();
        // 获取男性/女性总数
        List<ClientTypeDTO> clientTypeCount = orderComboService.getClientTypeCount();
        ProfileBasicInfoVO profileBasicInfoVO = new ProfileBasicInfoVO();
        profileBasicInfoVO.setOrderType(orderTypeCount);
        profileBasicInfoVO.setClientType(clientTypeCount);
        return profileBasicInfoVO;
    }

    @Override
    public List<ProductsTopSalesVO> productsTopSales() {
        List<ProductsTopSalesDTO> productsTopSalesDTOS = orderListService.productsTopSales();
        List<ProductsTopSalesVO> productsTopSalesVOS = BeanUtil.copyToList(productsTopSalesDTOS, ProductsTopSalesVO.class);
        return productsTopSalesVOS;
    }

    @Override
    public MultiSeriesDataResponse salesTrends() {
        DateTime date = DateUtil.date();
        // 本周开始结束时间
        DateTime startOfWeek = DateUtil.beginOfWeek(date);
        DateTime endOfWeek = DateUtil.endOfWeek(date);
        // 上周开始结束时间
        DateTime dateTime = DateUtil.lastWeek();
        DateTime lastStartOfWeek = DateUtil.beginOfWeek(dateTime);
        DateTime lastEndOfWeek = DateUtil.endOfWeek(dateTime);

        List<SalesTrendsDTO> salesTrendsDTOS = orderListService.salesTrends(lastStartOfWeek, endOfWeek);


        Map<Date, Long> thisWeekSales = new HashMap<>();
        Map<Date, Long> lastWeekSales = new HashMap<>();
        salesTrendsDTOS.stream().forEach(item -> {
            // 本周
            boolean thisWeek = DateUtil.isIn(item.getOrderDay(), startOfWeek, endOfWeek);
            // 本周
            boolean lastWeek = DateUtil.isIn(item.getOrderDay(), lastStartOfWeek, lastEndOfWeek);
            if (thisWeek) {
                thisWeekSales.put(item.getOrderDay(), item.getCount());
            } else if (lastWeek) {
                lastWeekSales.put(item.getOrderDay(), item.getCount());
            }
        });
        List<DateTime> thisWeekRange = DateUtil.rangeToList(startOfWeek, endOfWeek, DateField.DAY_OF_MONTH, 1);
        List<DateTime> lastWeekRange = DateUtil.rangeToList(lastStartOfWeek, lastEndOfWeek, DateField.DAY_OF_MONTH, 1);
        String[] xAxisData = thisWeekRange.stream().map(item -> {
            Week week = item.dayOfWeekEnum();
            return week.toChinese("周");
        }).toArray(String[]::new);
        long[] dataA = thisWeekRange.stream().mapToLong(item -> thisWeekSales.getOrDefault(item, 0L)).toArray();
        long[] dataB = lastWeekRange.stream().mapToLong(item -> lastWeekSales.getOrDefault(item, 0L)).toArray();

        List<SeriesData> series = new ArrayList<>();
        series.add(new SeriesData("本周", dataA));
        series.add(new SeriesData("上周", dataB));
        MultiSeriesDataResponse multiSeriesDataResponse = new MultiSeriesDataResponse(xAxisData, series);

        return multiSeriesDataResponse;
    }

    @Override
    public Long devicesTotalDeployed() {
        Long count = machineMapper.machineCount();
        return count;
    }

    @Override
    public List<DevicesDistrictDeployedVO> devicesDistrictDeployed() {
        List<DevicesDistrictDeployedDTO> devicesDistrictDeployedDTOS = machineMapper.machineDistrictCount();

        List<String> areaIds = devicesDistrictDeployedDTOS.stream().map(DevicesDistrictDeployedDTO::getAreaId).distinct().collect(Collectors.toList());
        List<Area> areas = areaService.listByIds(areaIds);
        List<String> countyIds = areas.stream().map(Area::getCountyId).distinct().collect(Collectors.toList());
        Map<String, Area> areaMapByAreaId = areas.stream().collect(Collectors.toMap(Area::getAreaId, Function.identity()));

        List<TCounty> tCounties = tCountyService.listByIds(countyIds);
        Map<String, TCounty> countiesMapById = tCounties.stream().collect(Collectors.toMap(TCounty::getId, Function.identity()));

        List<DevicesDistrictDeployedVO> devicesDistrictDeployedVOS = devicesDistrictDeployedDTOS.stream().map(item -> {
            DevicesDistrictDeployedVO bean = BeanUtil.toBean(item, DevicesDistrictDeployedVO.class);

            Area area = areaMapByAreaId.getOrDefault(item.getAreaId(), new Area());
            bean.setAreaName(StrUtil.subAfter(area.getName(), "/", true));

            TCounty tCounty = countiesMapById.getOrDefault(area.getCountyId(), new TCounty());
            bean.setGeo(tCounty.getGeo());

            return bean;
        }).collect(Collectors.toList());
        return devicesDistrictDeployedVOS;
    }

    @Override
    public List<SalesRankingVO> salesRanking() {
        List<SalesRankingDTO> salesRankingDTOS = orderListService.salesRanking();
        List<String> positionIds = salesRankingDTOS.stream().map(SalesRankingDTO::getPositionId).collect(Collectors.toList());
        List<PositionDTO> positionDTOS = positionService.queryNameByIds(positionIds);
        Map<String, PositionDTO> positionDTOMapById = positionDTOS.stream().collect(Collectors.toMap(PositionDTO::getPositionId, Function.identity()));
        List<SalesRankingVO> salesRankingVOS = BeanUtil.copyToList(salesRankingDTOS, SalesRankingVO.class).stream().peek(item -> {
            PositionDTO positionDTO = positionDTOMapById.getOrDefault(item.getPositionId(), new PositionDTO());
            item.setAreaName(StrUtil.subAfter(positionDTO.getAreaName(), "/", true));
            item.setPositionName(positionDTO.getPositionName());
        }).sorted(Comparator.comparing(SalesRankingVO::getPrice, Comparator.reverseOrder()).thenComparing(SalesRankingVO::getCount, Comparator.reverseOrder())).collect(Collectors.toList());
        return salesRankingVOS;
    }

    @Override
    public BigDecimal salesRealtime() {
        BigDecimal bigDecimal = orderListService.salesRealtime();
        return bigDecimal;
    }
}
